package com.coffee.codegen;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.coffee.common.util.IdUtil;
import com.google.common.collect.Maps;

import java.util.*;

/**
 * 代码生成工具类
 * @author Kevin
 */
@SuppressWarnings("ALL")
public class CodeGenerator {

    public static final String JDBC_URL = "jdbc:mysql://localhost:3306/coffee-dev?characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai";
    public static final String JDBC_USERNAME = "root";
    public static final String JDBC_PASSWORD = "123456";
    public static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";

    /** 按照个人需要，进行修改 */
    public static final String AUTHOR = "Kevin";
    public static final String PROJECT_PATH = "D:\\tempCode";
    public static final String PACKAGE_PARENT = "com.coffee";
    public static final String MODULE_NAME = "system";

    /** 生成SQL脚本的上级菜单的ID，要开发的功能，需要放到XXX菜单下面，请找到XXX菜单的ID */
    public static final String PARENT_MENU_ID = "1406064334403878913";

    /** admin的ID，可以不用修改 */
    public static final String CREATE_BY = "1";
    public static final String UPDATE_BY = "1";

    /** 默认菜单图标，可以不用修改，SQL脚本生成之后，在页面选择图标，进行修改即可 */
    public static final String ICON = "ant-design:unordered-list-outlined";

    // 是否导出excel
    public static final Boolean exportExcel = false;

    public static void main(String[] args) {
        new CodeGenerator().generate(
                "sys_example"
        );
    }

    private void generate(String... tableNamesInclude) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = PROJECT_PATH;
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor(AUTHOR);
        gc.setOpen(false);
        gc.setDateType(DateType.ONLY_DATE);
        //默认不覆盖，如果文件存在，将不会再生成，配置true就是覆盖
        gc.setFileOverride(true);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        gc.setBaseResultMap(true);
        // gc.setBaseColumnList(true); // XML column list
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(JDBC_URL);
        dsc.setDriverName(JDBC_DRIVER);
        dsc.setUsername(JDBC_USERNAME);
        dsc.setPassword(JDBC_PASSWORD);
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        // 设置模块名，会在指定parent包下生成一个指定的模块包
        pc.setModuleName(MODULE_NAME);
        pc.setParent(PACKAGE_PARENT);
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
                Arrays.asList(tableNamesInclude).forEach(item -> {
                    Map params = Objects.isNull(this.getMap()) ? Maps.newHashMap() : this.getMap();
                    params.put(item +"menuId", IdUtil.getSnowflakeId());
                    params.put(item +"parentMenuId", PARENT_MENU_ID);
                    params.put(item +"icon", ICON);
                    params.put(item +"pageButtonId", IdUtil.getSnowflakeId());
                    params.put(item +"addButtonId", IdUtil.getSnowflakeId());
                    params.put(item +"editButtonId", IdUtil.getSnowflakeId());
                    params.put(item +"removeButtonId", IdUtil.getSnowflakeId());
                    params.put(item +"viewButtonId", IdUtil.getSnowflakeId());
                    params.put(item +"exportButtonId", IdUtil.getSnowflakeId());
                    params.put(item +"createBy", CREATE_BY);
                    params.put(item +"updateBy", UPDATE_BY);
                    params.put(item +"exportExcel", exportExcel);
                    this.setMap(params);
                });
            }
        };

        // 如果模板引擎是 freemarker
        // String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        // 调整xml生成目录
        focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        // 生成自定义模板
        focList.add(new FileOutConfig("/templates/addDTO.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String path = PACKAGE_PARENT.replaceAll("\\." , "/") + "/" + MODULE_NAME.replaceAll("\\." , "/");
                return projectPath + "/src/main/java/" + path + "/common/dto/" + tableInfo.getEntityName() + "AddDTO" + StringPool.DOT_JAVA;
            }
        });
        // 生成自定义模板
        focList.add(new FileOutConfig("/templates/editDTO.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String path = PACKAGE_PARENT.replaceAll("\\." , "/") + "/" + MODULE_NAME.replaceAll("\\." , "/");
                return projectPath + "/src/main/java/" + path + "/common/dto/" + tableInfo.getEntityName() + "EditDTO" + StringPool.DOT_JAVA;
            }
        });
        // 生成自定义模板
        focList.add(new FileOutConfig("/templates/queryDTO.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String path = PACKAGE_PARENT.replaceAll("\\." , "/") + "/" + MODULE_NAME.replaceAll("\\." , "/");
                return projectPath + "/src/main/java/" + path + "/common/dto/" + tableInfo.getEntityName() + "QueryDTO" + StringPool.DOT_JAVA;
            }
        });
        // 生成自定义模板，SQL
        focList.add(new FileOutConfig("/templates/sql.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/" + tableInfo.getName() + "_sql.sql";
            }
        });
        // 生成自定义模板，VUE
        focList.add(new FileOutConfig("/templates/vue/api.ts.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/vue/" + tableInfo.getEntityPath() +"/" + tableInfo.getEntityPath() + "Api.ts";
            }
        });
        // 生成自定义模板，VUE
        focList.add(new FileOutConfig("/templates/vue/data.ts.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/vue/" + tableInfo.getEntityPath() +"/" + "data.ts";
            }
        });
        // 生成自定义模板，VUE
        focList.add(new FileOutConfig("/templates/vue/FormModal.vue.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/vue/" + tableInfo.getEntityPath() +"/" + "FormModal.vue";
            }
        });
        // 生成自定义模板，VUE
        focList.add(new FileOutConfig("/templates/vue/index.vue.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/vue/" + tableInfo.getEntityPath() +"/" + "index.vue";
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null)
                .setEntity("/templates/entity.java.vm")
                .setMapper("/templates/mapper.java.vm")
                .setController("/templates/controller.java.vm")
                .setService("/templates/service.java.vm")
                .setServiceImpl("/templates/serviceImpl.java.vm");
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(tableNamesInclude);
        strategy.setChainModel(false);
        List<TableFill> tableFillList = new ArrayList<>();
        tableFillList.add(new TableFill("create_by" , FieldFill.INSERT));
        tableFillList.add(new TableFill("create_time" , FieldFill.INSERT));
        tableFillList.add(new TableFill("update_by" , FieldFill.INSERT_UPDATE));
        tableFillList.add(new TableFill("update_time" , FieldFill.INSERT_UPDATE));
        strategy.setTableFillList(tableFillList);
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new VelocityTemplateEngine());
        mpg.execute();
        System.out.println(mpg.getTemplateEngine().getObjectMap(new TableInfo()));
    }

}
